package com.dog.basics.service.mtkj.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dog.basics.bean.dto.admin.mtkj.OrderEditDto;
import com.dog.basics.bean.dto.admin.mtkj.OrderFromDto;
import com.dog.basics.bean.dto.api.mtkj.ApiEndOrderAddDto;
import com.dog.basics.bean.dto.api.mtkj.ApiGOrderAddDto;
import com.dog.basics.bean.dto.api.mtkj.ApiLyOrderAddDto;
import com.dog.basics.bean.dto.api.mtkj.ApiOrderFromDto;
import com.dog.basics.bean.dto.netty.NettyWheelchairDto;
import com.dog.basics.bean.model.common.DogUser;
import com.dog.basics.bean.model.common.DogUserConnect;
import com.dog.basics.bean.model.mtkj.*;
import com.dog.basics.bean.model.sys.SysUser;
import com.dog.basics.bean.vo.admin.mtkj.OrderVo;
import com.dog.basics.bean.vo.api.mtkj.ApiOrderPrepayVo;
import com.dog.basics.bean.vo.api.mtkj.ApiOrderVo;
import com.dog.basics.common.constant.CommonConstants;
import com.dog.basics.common.util.*;
import com.dog.basics.dao.common.DogUserConnectMapper;
import com.dog.basics.dao.common.DogUserMapper;
import com.dog.basics.dao.mtkj.*;
import com.dog.basics.dao.sys.SysUserMapper;
import com.dog.basics.security.util.SecurityUtils;
import com.dog.basics.service.common.WeChatMiniService;
import com.dog.basics.service.mtkj.IMtDeviceLockPassService;
import com.dog.basics.service.mtkj.IMtDeviceOrderService;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.log4j.Log4j2;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * 设备订单 服务实现类
 * </p>
 *
 * @author wph
 * @since 2020-09-29
 */
@Log4j2
@Service
@AllArgsConstructor
public class MtDeviceOrderServiceImpl extends ServiceImpl<MtDeviceOrderMapper, MtDeviceOrder> implements IMtDeviceOrderService {
    private final MtDeviceHospitalMapper mtDeviceHospitalMapper;
    private final MtDeviceWheelchairMapper mtDeviceWheelchairMapper;
    private final DogUserMapper dogUserMapper;
    private final SysUserMapper sysUserMapper;
    private final MtDeviceLockMapper mtDeviceLockMapper;
    private final MtDeviceLockPassMapper mtDeviceLockPassMapper;
    private final DogUserConnectMapper dogUserConnectMapper;
    private final WeChatMiniService weChatMiniService;
    private final MtDeviceHospitalCostMapper mtDeviceHospitalCostMapper;
    private final MtDeviceFlowingWaterMapper mtDeviceFlowingWaterMapper;
    private final MtDeviceHospitalWheelchairMapper mtDeviceHospitalWheelchairMapper;
    private final RedissonClient redissonClient;
    private final RabbitTemplate rabbitTemplate;
    private final MtDeviceDepositMapper mtDeviceDepositMapper;

    /**
     * 分页的条件公用类
     *
     * @param name,mobile
     * @param userIds
     */
    public List<Long> getuserIdsWhere(String name, String mobile, List<Long> userIds) {
        List<Long> collect = dogUserMapper.selectList(Wrappers.<DogUser>lambdaQuery().like(StrUtil.isNotBlank(mobile), DogUser::getUserMobile, mobile).like(StrUtil.isNotBlank(name), DogUser::getNickName, name)).stream().map(e -> e.getUserId()).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(collect)) {
            userIds = collect;
        } else {
            userIds.add(-2L);
        }
        return userIds;
    }

    /**
     * 分页的条件公用类
     *
     * @param name,mobile
     * @param sysuserIds
     */
    public List<Long> getsysuserIdsWhere(String name, List<Long> sysuserIds) {
        List<Long> collect = sysUserMapper.selectList(Wrappers.<SysUser>lambdaQuery().like(StrUtil.isNotBlank(name), SysUser::getUsername, name)).stream().map(e -> e.getUserId()).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(collect)) {
            sysuserIds = collect;
        } else {
            sysuserIds.add(-2L);
        }
        return sysuserIds;
    }

    /**
     * 分页的条件公用类
     *
     * @param name,mobile
     * @param hospitalIds
     */
    public List<Long> gethospitalIdsWhere(String name, List<Long> hospitalIds) {
        List<Long> collect = mtDeviceHospitalMapper.selectList(Wrappers.<MtDeviceHospital>lambdaQuery().like(StrUtil.isNotBlank(name), MtDeviceHospital::getHospitalName, name)).stream().map(e -> e.getId()).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(collect)) {
            hospitalIds = collect;
        } else {
            hospitalIds.add(-2L);
        }
        return hospitalIds;
    }

    /**
     * 分页的条件公用类
     *
     * @param name,mobile
     * @param codeIds
     */
    public List<Long> getCodeIdsWhere(String name, List<Long> codeIds) {
        List<Long> collect = mtDeviceWheelchairMapper.selectList(Wrappers.<MtDeviceWheelchair>lambdaQuery().like(StrUtil.isNotBlank(name), MtDeviceWheelchair::getWheeCode, name)).stream().map(e -> e.getId()).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(collect)) {
            codeIds = collect;
        } else {
            codeIds.add(-2L);
        }
        return codeIds;
    }

    /**
     * @Description: 分页设备订单
     * @Param: status
     * @return: IPage<OrderVo>
     * @Author: wph
     * @Date:
     */
    @Override
    public IPage<OrderVo> getPageList(PageParam page, OrderFromDto obj) {
        Long userId = null;
        //权限判断
        if (SecurityUtils.getSysUser().getAccountType() == 2) {
            userId = SecurityUtils.getSysUser().getUserId();
        }
        // 判断所属医院ID
        List<Long> hospitalIds = CollUtil.newArrayList();
        if (StrUtil.isNotBlank(obj.getOrderDeviceHospitalName())) {
            hospitalIds = gethospitalIdsWhere(obj.getOrderDeviceHospitalName(), hospitalIds);
        }
        // 判断所属轮椅编号ID
        List<Long> codeIds = CollUtil.newArrayList();
        if (StrUtil.isNotBlank(obj.getOrderDeviceWheelchairCode())) {
            codeIds = getCodeIdsWhere(obj.getOrderDeviceWheelchairCode(), codeIds);
        }
        // 判断所属用户ID
        List<Long> userIds = CollUtil.newArrayList();
        if (StrUtil.isNotBlank(obj.getOrderAgentUserName()) || StrUtil.isNotBlank(obj.getOrderUserMobile())) {
            userIds = getuserIdsWhere(obj.getOrderAgentUserName(), obj.getOrderUserMobile(), userIds);
        }
        // 判断所属代理商ID
        List<Long> sysuserIds = CollUtil.newArrayList();
        if (StrUtil.isNotBlank(obj.getOrderAgentUserName())) {
            sysuserIds = getsysuserIdsWhere(obj.getOrderAgentUserName(), sysuserIds);
        }
        this.page(page, new LambdaQueryWrapper<MtDeviceOrder>()
                .eq(ObjectUtil.isNotNull(userId), MtDeviceOrder::getOrderAgentUserId, userId)
                .in(CollUtil.isNotEmpty(hospitalIds), MtDeviceOrder::getOrderDeviceHospitalId, hospitalIds)
                .in(CollUtil.isNotEmpty(codeIds), MtDeviceOrder::getOrderDeviceWheelchairId, codeIds)
                .in(CollUtil.isNotEmpty(sysuserIds), MtDeviceOrder::getOrderAgentUserId, sysuserIds)
                .in(CollUtil.isNotEmpty(userIds), MtDeviceOrder::getOrderUserId, userIds)
                .eq(ObjectUtil.isNotNull(obj.getOrderDeviceHospitalId()), MtDeviceOrder::getOrderDeviceHospitalId, obj.getOrderDeviceHospitalId())
                .eq(ObjectUtil.isNotNull(obj.getOrderDeviceWheelchairId()), MtDeviceOrder::getOrderDeviceWheelchairId, obj.getOrderDeviceWheelchairId())
                .eq(ObjectUtil.isNotNull(obj.getOrderAgentUserId()), MtDeviceOrder::getOrderAgentUserId, obj.getOrderAgentUserId())
                .eq(ObjectUtil.isNotNull(obj.getOrderUserId()), MtDeviceOrder::getOrderUserId, obj.getOrderUserId())
                .eq(ObjectUtil.isNotNull(obj.getOrderPayState()), MtDeviceOrder::getOrderPayState, obj.getOrderPayState())
                .eq(ObjectUtil.isNotNull(obj.getOrderState()), MtDeviceOrder::getOrderState, obj.getOrderState())
                .like(StrUtil.isNotBlank(obj.getOrderNo()), MtDeviceOrder::getOrderNo, obj.getOrderNo())
                .like(StrUtil.isNotBlank(obj.getSerialNo()), MtDeviceOrder::getSerialNo, obj.getSerialNo())
                .gt(ObjectUtil.isNotNull(obj.getEndTime()), MtDeviceOrder::getCreateTime, obj.getStartTime())
                .lt(ObjectUtil.isNotNull(obj.getStartTime()), MtDeviceOrder::getCreateTime, obj.getEndTime())
                .orderBy(Boolean.TRUE, obj.getIsOrderByAvg(), MtDeviceOrder::getCreateTime));

        List<MtDeviceOrder> records = page.getRecords();
        page.setRecords(records.stream().map(e -> {
            OrderVo newsVo = BeanUtil.toBean(e, OrderVo.class);
            //查询
            MtDeviceHospital mtDeviceHospital = mtDeviceHospitalMapper.selectById(e.getOrderDeviceHospitalId());
            MtDeviceWheelchair mtDeviceWheelchair = mtDeviceWheelchairMapper.selectById(e.getOrderDeviceWheelchairId());
            MtDeviceLock mtDeviceLock = mtDeviceLockMapper.selectById(e.getOrderGetDeviceLockId());
            MtDeviceLock mtDeviceLock1 = mtDeviceLockMapper.selectById(e.getOrderPutDeviceLockId());
            MtDeviceLockPass mtDeviceLockPass = mtDeviceLockPassMapper.selectById(e.getOrderGetDeviceLockPassId());
            MtDeviceLockPass mtDeviceLockPass1 = mtDeviceLockPassMapper.selectById(e.getOrderPutDeviceLockPassId());
            DogUser dogUser = dogUserMapper.selectById(e.getOrderUserId());
            SysUser sysUser = sysUserMapper.selectById(e.getOrderAgentUserId());
            newsVo.setOrderUserName(ObjectUtil.isNotNull(dogUser) ? dogUser.getNickName() : "");
            newsVo.setOrderUserMobile(ObjectUtil.isNotNull(dogUser) ? dogUser.getUserMobile() : "");
            newsVo.setOrderDeviceHospitalName(ObjectUtil.isNotNull(mtDeviceHospital) ? mtDeviceHospital.getHospitalName() : "");
            newsVo.setOrderAgentUserName(ObjectUtil.isNotNull(sysUser) ? sysUser.getUsername() : "");
            newsVo.setOrderGetDeviceLockAddress(ObjectUtil.isNotNull(mtDeviceLock) ? mtDeviceLock.getDetailedAddress() : "");
            newsVo.setOrderPutDeviceLockAddress(ObjectUtil.isNotNull(mtDeviceLock1) ? mtDeviceLock1.getDetailedAddress() : "");
            newsVo.setOrderDeviceWheelchairCode(ObjectUtil.isNotNull(mtDeviceWheelchair) ? mtDeviceWheelchair.getWheeCode() : "");
            newsVo.setOrderGetDeviceLockCode(ObjectUtil.isNotNull(mtDeviceLock) ? mtDeviceLock.getDevCode() : "");
            newsVo.setOrderPutDeviceLockCode(ObjectUtil.isNotNull(mtDeviceLock1) ? mtDeviceLock1.getDevCode() : "");
            newsVo.setOrderGetDeviceLockPassNum(ObjectUtil.isNotNull(mtDeviceLockPass) ? mtDeviceLockPass.getPassNum() : "");
            newsVo.setOrderPutDeviceLockPassNum(ObjectUtil.isNotNull(mtDeviceLockPass1) ? mtDeviceLockPass1.getPassNum() : "");
            return newsVo;
        }).collect(Collectors.toList()));
        return page;
    }

    /**
     * @Description: APP分页设备订单
     * @Param: status
     * @return: IPage<OrderVo>
     * @Author: wph
     * @Date:
     */
    @Override
    public IPage<ApiOrderVo> getApiPageList(PageParam page, ApiOrderFromDto obj) {

        this.page(page, new LambdaQueryWrapper<MtDeviceOrder>()
                .eq(ObjectUtil.isNotNull(obj.getId()), MtDeviceOrder::getId, obj.getId())
                .eq(MtDeviceOrder::getOrderUserId, SecurityUtils.getUser().getUserId())
                .eq(ObjectUtil.isNotNull(obj.getOrderState()), MtDeviceOrder::getOrderState, obj.getOrderState())
                .orderBy(Boolean.TRUE, obj.getIsOrderByAvg(), MtDeviceOrder::getCreateTime));
        List<MtDeviceOrder> records = page.getRecords();
        page.setRecords(records.stream().map(e -> {
            ApiOrderVo newsVo = new ApiOrderVo();
            BeanUtil.copyProperties(e, newsVo);
            //查询
            MtDeviceHospital mtDeviceHospital = mtDeviceHospitalMapper.selectById(e.getOrderDeviceHospitalId());
            MtDeviceWheelchair mtDeviceWheelchair = mtDeviceWheelchairMapper.selectById(e.getOrderDeviceWheelchairId());
            MtDeviceLock mtDeviceLock = mtDeviceLockMapper.selectById(e.getOrderGetDeviceLockId());
            MtDeviceLock mtDeviceLock1 = mtDeviceLockMapper.selectById(e.getOrderPutDeviceLockId());
            MtDeviceLockPass mtDeviceLockPass = mtDeviceLockPassMapper.selectById(e.getOrderGetDeviceLockPassId());
            MtDeviceLockPass mtDeviceLockPass1 = mtDeviceLockPassMapper.selectById(e.getOrderPutDeviceLockPassId());
            newsVo.setOrderDeviceHospitalName(ObjectUtil.isNotNull(mtDeviceHospital) ? mtDeviceHospital.getHospitalName() : "");
            newsVo.setOrderGetDeviceLockAddress(ObjectUtil.isNotNull(mtDeviceLock) ? mtDeviceLock.getDetailedAddress() : "");
            newsVo.setOrderPutDeviceLockAddress(ObjectUtil.isNotNull(mtDeviceLock1) ? mtDeviceLock1.getDetailedAddress() : "");
            newsVo.setOrderDeviceWheelchairCode(ObjectUtil.isNotNull(mtDeviceWheelchair) ? mtDeviceWheelchair.getWheeCode() : "");
            newsVo.setOrderGetDeviceLockPassNum(ObjectUtil.isNotNull(mtDeviceLockPass) ? mtDeviceLockPass.getPassNum() : "");
            newsVo.setOrderPutDeviceLockPassNum(ObjectUtil.isNotNull(mtDeviceLockPass1) ? mtDeviceLockPass1.getPassNum() : "");
            newsVo.setWheeType(ObjectUtil.isNotNull(mtDeviceWheelchair) ? mtDeviceWheelchair.getWheeType() : 0);
            return newsVo;
        }).collect(Collectors.toList()));
        return page;
    }

    /**
     * @Description: 4G确认使用
     * @Param: OrderAddDto
     * @return: R
     * @Author: wph
     * @Date:
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @SneakyThrows
    public Boolean save4gObj(ApiGOrderAddDto obj) {
        MtDeviceLock dogNews = mtDeviceLockMapper.selectById(obj.getLockId());
        log.info("设备锁信息:{}", dogNews.toString());
        Validator.validateNotNull(dogNews, "设备锁不存在!");
        //查询设备通道号
        List<MtDeviceLockPass> list = mtDeviceLockPassMapper.selectList(Wrappers.<MtDeviceLockPass>lambdaQuery().eq(MtDeviceLockPass::getLockId, obj.getLockId()).eq(MtDeviceLockPass::getPassNum, obj.getPassNum()).orderByDesc(MtDeviceLockPass::getCreateTime));
        Validator.validateTrue(CollUtil.isNotEmpty(list), "设备锁通道不存在!");
        log.info("设备锁通道信息:{}", list.get(0).toString());
        MtDeviceLockPass mtDeviceLockPass = list.get(0);
        MtDeviceWheelchair mtDeviceWheelchair = mtDeviceWheelchairMapper.selectById(mtDeviceLockPass.getWheeId());
        Validator.validateNotNull(mtDeviceWheelchair, "轮椅不存在!");
        Validator.validateEqual(mtDeviceLockPass.getPassLockStatus(), 1, "设备通道未被占用!");
        // 判断是否开锁成功
        String formatRdisKey = StrUtil.format("{}@{}", CommonConstants.DEVICE_FOUR_G, mtDeviceLockPass.getId());
        if (obj.getFlage()) {
            log.info("开锁成功进入生成订单");
            //保存订单
            MtDeviceOrder mtDeviceOrder = new MtDeviceOrder();
            mtDeviceOrder.setOrderUserId(mtDeviceLockPass.getUserId());
            mtDeviceOrder.setOrderDeviceHospitalId(dogNews.getHospitalId());
            mtDeviceOrder.setOrderAgentUserId(dogNews.getDevAgentUserId());
            mtDeviceOrder.setSerialNo(serialNumberUtils.serialNumberGenerate().toString());
            mtDeviceOrder.setOrderMainNo(serialNumberUtils.serialNumberGenerate().toString());
            mtDeviceOrder.setOrderNo(serialNumberUtils.serialNumberGenerate().toString());
            mtDeviceOrder.setOrderGetDeviceLockId(dogNews.getId());
            mtDeviceOrder.setOrderGetDeviceLockPassId(mtDeviceLockPass.getId());
            mtDeviceOrder.setOrderDeviceWheelchairId(mtDeviceLockPass.getWheeId());
            mtDeviceOrder.setCreateTime(DateUtil.currentSeconds());
            mtDeviceOrder.setCreateBy(mtDeviceLockPass.getCreateBy());
            mtDeviceOrder.setOrderState(0);
            Validator.validateTrue(this.save(mtDeviceOrder), "保存订单失败!");
            //更新轮椅装填
            mtDeviceWheelchair.setWheeState(2);
            if (ObjectUtil.isNull(mtDeviceWheelchair.getWheeUseTime()) || Validator.equal(mtDeviceWheelchair.getWheeUseTime(), -1L)) {
                mtDeviceWheelchair.setWheeUseTime(DateUtil.currentSeconds());
            }
            Validator.validateTrue(retBool(mtDeviceWheelchairMapper.updateById(mtDeviceWheelchair)), "设备锁通道更新失败!");
            // 保存到 REDIS 开锁成功
            RedisUtil.set(formatRdisKey, "1", 15);
            mtDeviceLockPass.setWheeId(-1L);
            mtDeviceLockPass.setPassStatus(0);
            mtDeviceLockPass.setUserId(-1L);
            mtDeviceLockPass.setPassLockStatus(0);
            // 删除 REDIS 通道开锁 = 加锁
            String redisLockKey = StrUtil.format("LockDevicekKey:{}:{}", dogNews.getId(), mtDeviceLockPass.getId());
            RedisUtil.del(redisLockKey);
        } else {
            log.info("开锁失败修改锁通道");
            mtDeviceLockPass.setPassLockStatus(0);
            mtDeviceLockPass.setUserId(-1L);
            mtDeviceLockPass.setPassStatus(1);
            //保存到redis
            RedisUtil.set(formatRdisKey, "0", 15);
        }
        Validator.validateTrue(retBool(mtDeviceLockPassMapper.updateById(mtDeviceLockPass)), "设备锁通道更新失败!");
        return Boolean.TRUE;
    }

    /**
     * @Description: 4G轮训接口
     * @Param: OrderAddDto
     * @return: R
     * @Author: wph
     * @Date:
     */
    @Override
    public Integer get4gObj(Long lockPassId) {
        MtDeviceLockPass mtDeviceLockPass = mtDeviceLockPassMapper.selectById(lockPassId);
        Validator.validateNotNull(mtDeviceLockPass, "设备锁通道不存在!");

        // 先判断是否被占用
        if (Validator.equal(mtDeviceLockPass.getPassLockStatus(), 1)) {
            Validator.validateEqual(mtDeviceLockPass.getUserId(), SecurityUtils.getUser().getUserId(), "设备通道被占用");
        }
        // 获取redis中应答信息
        String formatRdisKey = StrUtil.format("{}@{}", CommonConstants.DEVICE_FOUR_G, lockPassId);
        // 判断是否有数据信息
        if (!RedisUtil.hasKey(formatRdisKey)) {
            System.out.println("轮训失败通道编号++++++++++++" + mtDeviceLockPass.getPassNum());
            return Integer.valueOf(0);
        }
        String redisCode = RedisUtil.get(formatRdisKey);
        System.out.println("轮训成功通道编号++++++++++++" + mtDeviceLockPass.getPassNum() + "值未++++" + redisCode);
        //删除redids
        RedisUtil.del(formatRdisKey);
        // 判断数据信息是否 - 开锁成功
        return Validator.equal(redisCode, "1") ? Integer.valueOf(1) : Integer.valueOf(2);


    }

    /**
     * @Description: 4G轮训接口为0的处理(网络中断)(待优化)
     * @Param: OrderAddDto
     * @return: R
     * @Author: wph
     * @Date:
     */
    @Override
    public Boolean get4gZeroObj(Long lockPassId) {
        MtDeviceLockPass mtDeviceLockPass = mtDeviceLockPassMapper.selectById(lockPassId);
        Validator.validateNotNull(mtDeviceLockPass, "设备锁通道不存在!");
        mtDeviceLockPass.setPassLockStatus(0);
        mtDeviceLockPass.setUserId(-1L);
        mtDeviceLockPass.setPassStatus(1);
        Validator.validateTrue(retBool(mtDeviceLockPassMapper.updateById(mtDeviceLockPass)), "设备锁通道更新失败!");
        return Boolean.TRUE;
    }

    /**
     * @Description: 4G开始使用
     * @Param: OrderAddDto
     * @return: R
     * @Author: wph
     * @Date:
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @SneakyThrows
    public Boolean save4gStartObj(ApiLyOrderAddDto obj) {
        log.info("4G开始使用");
        MtDeviceLockPass mtDeviceLockPass = mtDeviceLockPassMapper.selectById(obj.getLockPassId());
        Validator.validateNotNull(mtDeviceLockPass, "设备锁通道不存在!");
        // 先判断是否被占用
        if (Validator.equal(mtDeviceLockPass.getPassLockStatus(), 1)) {
            Validator.validateEqual(mtDeviceLockPass.getUserId(), SecurityUtils.getUser().getUserId(), "设备通道被占用");
        }
        MtDeviceLock dogNews = mtDeviceLockMapper.selectById(mtDeviceLockPass.getLockId());
        Validator.validateNotNull(dogNews, "设备锁不存在!");
        Validator.validateEqual(dogNews.getDevOnlineState(), 1, "设备不在线");
        MtDeviceWheelchair mtDeviceWheelchair = mtDeviceWheelchairMapper.selectById(mtDeviceLockPass.getWheeId());
        Validator.validateNotNull(mtDeviceWheelchair, "设备不存在!");

        List<MtDeviceHospitalCost> mtDeviceHospitalCostList = mtDeviceHospitalCostMapper.selectList(Wrappers.<MtDeviceHospitalCost>lambdaQuery().eq(MtDeviceHospitalCost::getDeviceHospitalId, dogNews.getHospitalId()).eq(MtDeviceHospitalCost::getWheeType, mtDeviceWheelchair.getWheeType()).orderByDesc(MtDeviceHospitalCost::getCreateTime));
        Validator.validateTrue(CollUtil.isNotEmpty(mtDeviceHospitalCostList), "该医院未设置费用!");
        //判断是否缴纳押金
        List<MtDeviceDeposit> list = mtDeviceDepositMapper.selectList(Wrappers.<MtDeviceDeposit>lambdaQuery().eq(MtDeviceDeposit::getDepositState, 1).eq(MtDeviceDeposit::getDepositUserId, SecurityUtils.getUser().getUserId()).orderByDesc(MtDeviceDeposit::getCreateTime));
        if (CollUtil.isNotEmpty(list)) {
            //判断类型和医院
            MtDeviceDeposit mtDeviceDeposit = list.get(0);
            //相同的医院
            if (Validator.equal(mtDeviceDeposit.getHospitalId(), dogNews.getHospitalId())) {
                //  Validator.validateEqual(mtDeviceDeposit.getHospitalId(), dogNews.getHospitalId(), "您缴纳的押金不是该医院的,如需使用其他产品请退押金之后重新扫描二维码!");
                if (Validator.equal(mtDeviceDeposit.getWheeType(), mtDeviceWheelchair.getWheeType())) {
                    //在判断金额是否相同costWheelchairDeposit
                    if (mtDeviceDeposit.getDepositMoney().compareTo(mtDeviceHospitalCostList.get(0).getCostWheelchairDeposit()) >= 0) {
                    } else {
                        if (mtDeviceWheelchair.getWheeType() == 0) {
                            Validator.validateTrue(Boolean.FALSE, "轮椅押金发生变化,如需使用其他产品请退押金之后重新扫描二维码!");
                        } else if (mtDeviceWheelchair.getWheeType() == 1) {
                            Validator.validateTrue(Boolean.FALSE, "平推车押金发生变化,如需使用其他产品请退押金之后重新扫描二维码!");
                        } else {
                            Validator.validateTrue(Boolean.FALSE, "陪护床押金发生变化,如需使用其他产品请退押金之后重新扫描二维码!");
                        }
                    }
                } else {
                    if (mtDeviceWheelchair.getWheeType() == 0) {
                        Validator.validateTrue(Boolean.FALSE, "正在使用的产品是轮椅,如需使用其他产品请退押金之后重新扫描二维码!");
                    } else if (mtDeviceWheelchair.getWheeType() == 1) {
                        Validator.validateTrue(Boolean.FALSE, "正在使用的产品是平推车,如需使用其他产品请退押金之后重新扫描二维码!");
                    } else {
                        Validator.validateTrue(Boolean.FALSE, "正在使用的产品是陪护床,如需使用其他产品请退押金之后重新扫描二维码!");
                    }
                }
                //不同的医院
            } else {
                if (Validator.equal(mtDeviceDeposit.getWheeType(), mtDeviceWheelchair.getWheeType())) {
                    //在判断金额是否相同costWheelchairDeposit
                    if (mtDeviceDeposit.getDepositMoney().compareTo(mtDeviceHospitalCostList.get(0).getCostWheelchairDeposit()) >= 0) {
                    } else {
                        if (mtDeviceWheelchair.getWheeType() == 0) {
                            Validator.validateTrue(Boolean.FALSE, "您缴纳的轮椅押金不是该医院的,如需使用其他产品请退押金之后重新扫描二维码!");
                        } else if (mtDeviceWheelchair.getWheeType() == 1) {
                            Validator.validateTrue(Boolean.FALSE, "您缴纳的平推车押金不是该医院的,如需使用其他产品请退押金之后重新扫描二维码!");
                        } else {
                            Validator.validateTrue(Boolean.FALSE, "您缴纳的陪护床押金不是该医院的,如需使用其他产品请退押金之后重新扫描二维码!");
                        }
                    }
                } else {
                    if (mtDeviceWheelchair.getWheeType() == 0) {
                        Validator.validateTrue(Boolean.FALSE, "正在使用的产品是轮椅,如需使用其他产品请退押金之后重新扫描二维码!");
                    } else if (mtDeviceWheelchair.getWheeType() == 1) {
                        Validator.validateTrue(Boolean.FALSE, "正在使用的产品是平推车,如需使用其他产品请退押金之后重新扫描二维码!");
                    } else {
                        Validator.validateTrue(Boolean.FALSE, "正在使用的产品是陪护床,如需使用其他产品请退押金之后重新扫描二维码!");
                    }
                }

            }

        } else {
            Validator.validateTrue(Boolean.FALSE, "请先缴纳押金!");
        }

        //  加锁
        RLock lock = redissonClient.getLock(StrUtil.format("anyLock:{}", dogNews.getId()));
        try {
            Boolean flage = lock.tryLock(10, 80, TimeUnit.SECONDS);
            if (flage) {
                log.info("4G开始使用进入修改锁通道");
                mtDeviceLockPass.setPassLockStatus(1);
                mtDeviceLockPass.setUserId(SecurityUtils.getUser().getUserId());
                // 判断修改成功
                SpringContextUtils.getBean(IMtDeviceLockPassService.class).editMtDeviceLockPassById(mtDeviceLockPass);

                // 判断当前通道是否加锁
                String redisLockKey = StrUtil.format("LockDevicekKey:{}:{}", dogNews.getId(), mtDeviceLockPass.getId());
                if (RedisUtil.hasKey(redisLockKey)) {
                    Boolean o = RedisUtil.get(redisLockKey);
                    log.info("4G开始使用判断当前通道是否加锁: {}", o);
                    Validator.validateFalse(o, "当前通道有扫码,请稍等");
                }
                // TODO if get lock success, do something;
                // 调用开锁
                NettyWheelchairDto.NettyWheelchairDtoBuilder nettyWheelchairDtoBuilder = NettyWheelchairDto.builder().msgType(10).devId(dogNews.getId()).lockport(Integer.valueOf(mtDeviceLockPass.getPassNum()));
                nettyWheelchairDtoBuilder.iDcard(mtDeviceWheelchair.getWheeCode());
                // 当前通道加锁情况
                RedisUtil.set(redisLockKey, Boolean.TRUE, 50);
                rabbitTemplate.convertAndSend("EX-WHEELCHAIR-MQ", "SERVICE-COMMON-WHEELCHAIR", nettyWheelchairDtoBuilder.build());
                // Thread.sleep(100);
            } else {
                log.info("4G开始使用当前锁扫码过多");
                Validator.validateTrue(Boolean.FALSE, "当前锁扫码过多,请稍受重试");
            }

        } catch (Exception e) {
            log.info("4G开始使用异常");
            Validator.validateTrue(Boolean.FALSE, "{}", e.getMessage());
        } finally {
            //TODO:释放锁
            if (ObjectUtil.isNotNull(lock) && lock.isHeldByCurrentThread()) {
                log.info("4G开始使用释放锁");
                lock.unlock();
            }
        }
        return Boolean.TRUE;

    }

    /**
     * @Description: 蓝牙开始使用
     * @Param: OrderAddDto
     * @return: R
     * @Author: wph
     * @Date:
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @SneakyThrows
    public Boolean saveLyObj(ApiLyOrderAddDto obj) {
        MtDeviceLockPass mtDeviceLockPass = mtDeviceLockPassMapper.selectById(obj.getLockPassId());
        Validator.validateNotNull(mtDeviceLockPass, "设备锁通道不存在!");
        MtDeviceLock dogNews = mtDeviceLockMapper.selectById(mtDeviceLockPass.getLockId());
        Validator.validateNotNull(dogNews, "设备锁不存在!");
        Validator.validateEqual(mtDeviceLockPass.getPassLockStatus(), 0, "设备通道被占用!");
        MtDeviceWheelchair mtDeviceWheelchair = mtDeviceWheelchairMapper.selectById(obj.getOrderDeviceWheelchairId());
        Validator.validateNotNull(mtDeviceWheelchair, "轮椅不存在!");
        List<MtDeviceHospitalCost> mtDeviceHospitalCostList = mtDeviceHospitalCostMapper.selectList(Wrappers.<MtDeviceHospitalCost>lambdaQuery().eq(MtDeviceHospitalCost::getDeviceHospitalId, dogNews.getHospitalId()).orderByDesc(MtDeviceHospitalCost::getCreateTime));
        Validator.validateTrue(CollUtil.isNotEmpty(mtDeviceHospitalCostList), "该医院未设置费用!");
        //判断是否缴纳押金
        List<MtDeviceDeposit> list = mtDeviceDepositMapper.selectList(Wrappers.<MtDeviceDeposit>lambdaQuery().eq(MtDeviceDeposit::getDepositState, 1).eq(MtDeviceDeposit::getDepositUserId, SecurityUtils.getUser().getUserId()).orderByDesc(MtDeviceDeposit::getCreateTime));
        if (CollUtil.isNotEmpty(list)) {
            //判断类型和医院
            MtDeviceDeposit mtDeviceDeposit = list.get(0);
            //相同的医院
            if (Validator.equal(mtDeviceDeposit.getHospitalId(), dogNews.getHospitalId())) {
                //  Validator.validateEqual(mtDeviceDeposit.getHospitalId(), dogNews.getHospitalId(), "您缴纳的押金不是该医院的,如需使用其他产品请退押金之后重新扫描二维码!");
                if (Validator.equal(mtDeviceDeposit.getWheeType(), mtDeviceWheelchair.getWheeType())) {
                    //在判断金额是否相同costWheelchairDeposit
                    if (mtDeviceDeposit.getDepositMoney().compareTo(mtDeviceHospitalCostList.get(0).getCostWheelchairDeposit()) >= 0) {
                    } else {
                        if (mtDeviceWheelchair.getWheeType() == 0) {
                            Validator.validateTrue(Boolean.FALSE, "轮椅押金发生变化,如需使用其他产品请退押金之后重新扫描二维码!");
                        } else if (mtDeviceWheelchair.getWheeType() == 1) {
                            Validator.validateTrue(Boolean.FALSE, "平推车押金发生变化,如需使用其他产品请退押金之后重新扫描二维码!");
                        } else {
                            Validator.validateTrue(Boolean.FALSE, "陪护床押金发生变化,如需使用其他产品请退押金之后重新扫描二维码!");
                        }
                    }
                } else {
                    if (mtDeviceWheelchair.getWheeType() == 0) {
                        Validator.validateTrue(Boolean.FALSE, "正在使用的产品是轮椅,如需使用其他产品请退押金之后重新扫描二维码!");
                    } else if (mtDeviceWheelchair.getWheeType() == 1) {
                        Validator.validateTrue(Boolean.FALSE, "正在使用的产品是平推车,如需使用其他产品请退押金之后重新扫描二维码!");
                    } else {
                        Validator.validateTrue(Boolean.FALSE, "正在使用的产品是陪护床,如需使用其他产品请退押金之后重新扫描二维码!");
                    }
                }
                //不同的医院
            } else {
                if (Validator.equal(mtDeviceDeposit.getWheeType(), mtDeviceWheelchair.getWheeType())) {
                    //在判断金额是否相同costWheelchairDeposit
                    if (mtDeviceDeposit.getDepositMoney().compareTo(mtDeviceHospitalCostList.get(0).getCostWheelchairDeposit()) >= 0) {
                    } else {
                        if (mtDeviceWheelchair.getWheeType() == 0) {
                            Validator.validateTrue(Boolean.FALSE, "您缴纳的轮椅押金不是该医院的,如需使用其他产品请退押金之后重新扫描二维码!");
                        } else if (mtDeviceWheelchair.getWheeType() == 1) {
                            Validator.validateTrue(Boolean.FALSE, "您缴纳的平推车押金不是该医院的,如需使用其他产品请退押金之后重新扫描二维码!");
                        } else {
                            Validator.validateTrue(Boolean.FALSE, "您缴纳的陪护床押金不是该医院的,如需使用其他产品请退押金之后重新扫描二维码!");
                        }
                    }
                } else {
                    if (mtDeviceWheelchair.getWheeType() == 0) {
                        Validator.validateTrue(Boolean.FALSE, "正在使用的产品是轮椅,如需使用其他产品请退押金之后重新扫描二维码!");
                    } else if (mtDeviceWheelchair.getWheeType() == 1) {
                        Validator.validateTrue(Boolean.FALSE, "正在使用的产品是平推车,如需使用其他产品请退押金之后重新扫描二维码!");
                    } else {
                        Validator.validateTrue(Boolean.FALSE, "正在使用的产品是陪护床,如需使用其他产品请退押金之后重新扫描二维码!");
                    }
                }

            }
        } else {
            Validator.validateTrue(Boolean.FALSE, "请先缴纳押金!");
        }
        mtDeviceLockPass.setPassLockStatus(1);
        Validator.validateTrue(retBool(mtDeviceLockPassMapper.updateById(mtDeviceLockPass)), "设备锁通道更新失败!");
        // 保存订单
        MtDeviceOrder mtDeviceOrder = new MtDeviceOrder();
        mtDeviceOrder.setOrderUserId(SecurityUtils.getUser().getUserId());
        mtDeviceOrder.setOrderDeviceHospitalId(dogNews.getHospitalId());
        mtDeviceOrder.setOrderAgentUserId(dogNews.getDevAgentUserId());
        mtDeviceOrder.setSerialNo(serialNumberUtils.serialNumberGenerate().toString());
        mtDeviceOrder.setOrderMainNo(serialNumberUtils.serialNumberGenerate().toString());
        mtDeviceOrder.setOrderNo(serialNumberUtils.serialNumberGenerate().toString());
        mtDeviceOrder.setOrderGetDeviceLockId(dogNews.getId());
        mtDeviceOrder.setOrderGetDeviceLockPassId(mtDeviceLockPass.getId());
        mtDeviceOrder.setOrderDeviceWheelchairId(obj.getOrderDeviceWheelchairId());
        mtDeviceOrder.setCreateTime(DateUtil.currentSeconds());
        mtDeviceOrder.setCreateBy(SecurityUtils.getUser().getUserId());
        mtDeviceOrder.setOrderState(0);
        Validator.validateTrue(this.save(mtDeviceOrder), "保存订单失败!");
        mtDeviceLockPass.setPassStatus(0);
        mtDeviceLockPass.setPassLockStatus(0);
        mtDeviceLockPass.setWheeId(-1L);
        Validator.validateTrue(retBool(mtDeviceLockPassMapper.updateById(mtDeviceLockPass)), "设备锁通道更新失败!");
        // 更新轮椅装填
        mtDeviceWheelchair.setWheeState(2);
        // 判断第一使用开始时间
        if (ObjectUtil.isNull(mtDeviceWheelchair.getWheeUseTime()) || Validator.equal(mtDeviceWheelchair.getWheeUseTime(), -1L)) {
            mtDeviceWheelchair.setWheeUseTime(DateUtil.currentSeconds());
        }
        Validator.validateTrue(retBool(mtDeviceWheelchairMapper.updateById(mtDeviceWheelchair)), "设备锁通道更新失败!");
        return Boolean.TRUE;
    }

    /**
     * @Description: 设备订单完成
     * @Param: OrderBasketAddDto
     * @return: R
     * @Author: wph
     * @Date:
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean endOrder(ApiEndOrderAddDto obj) {
        Validator.validateTrue(StrUtil.isNotBlank(obj.getOrderDeviceWheelchairId()), "设备轮椅不能为空!");
        Validator.validateFalse(Validator.equal(obj.getOrderDeviceWheelchairId(), "0000000000"), "设备编号不能为0000000000");
        MtDeviceLock dogNews = mtDeviceLockMapper.selectById(obj.getLockId());
        Validator.validateNotNull(dogNews, "设备锁不存在!");
        MtDeviceHospital mtDeviceHospital = mtDeviceHospitalMapper.selectById(dogNews.getHospitalId());
        Validator.validateNotNull(mtDeviceHospital, "医院不存在!");
        //查询设备通道号
        List<MtDeviceLockPass> list1 = mtDeviceLockPassMapper.selectList(Wrappers.<MtDeviceLockPass>lambdaQuery().eq(MtDeviceLockPass::getLockId, obj.getLockId()).eq(MtDeviceLockPass::getPassNum, obj.getPassNum()).orderByDesc(MtDeviceLockPass::getCreateTime));
        Validator.validateTrue(CollUtil.isNotEmpty(list1), "设备锁通道不存在!");
        //查询此设备是否在其他的地方
        MtDeviceLockPass mtDeviceLockPass = list1.get(0);
        MtDeviceWheelchair mtDeviceWheelchair = null;
        List<MtDeviceWheelchair> deviceWheelchairs = mtDeviceWheelchairMapper.selectList(Wrappers.<MtDeviceWheelchair>lambdaQuery().eq(MtDeviceWheelchair::getWheeCode, obj.getOrderDeviceWheelchairId()));
        if (CollUtil.isNotEmpty(deviceWheelchairs)) {
            mtDeviceWheelchair = deviceWheelchairs.get(0);
            //查询是否有其他的地方绑定了
            List<MtDeviceLockPass> mtDeviceLockPassList = mtDeviceLockPassMapper.selectList(Wrappers.<MtDeviceLockPass>lambdaQuery().eq(MtDeviceLockPass::getWheeId, mtDeviceWheelchair.getId()));
            Validator.validateFalse(CollUtil.isNotEmpty(mtDeviceLockPassList), "此设备还在其他通道属于异常归还!");
        } else {
            //创建轮椅
            mtDeviceWheelchair = new MtDeviceWheelchair();
            mtDeviceWheelchair.setWheeCode(obj.getOrderDeviceWheelchairId());
            mtDeviceWheelchair.setWheeName("默认");
            mtDeviceWheelchair.setWheeType(dogNews.getWheeType());
            mtDeviceWheelchair.setWheeState(2);
            mtDeviceWheelchair.setUseState(0);
            mtDeviceWheelchair.setProvinceId(mtDeviceHospital.getProvinceId());
            mtDeviceWheelchair.setCityId(mtDeviceHospital.getCityId());
            mtDeviceWheelchair.setAreaId(mtDeviceHospital.getAreaId());
            mtDeviceWheelchair.setDetailedAddress(mtDeviceHospital.getDetailedAddress());
            mtDeviceWheelchair.setCreateTime(DateUtil.currentSeconds());
            mtDeviceWheelchair.setCreateBy(1L);
            Validator.validateTrue(retBool(mtDeviceWheelchairMapper.insert(mtDeviceWheelchair)), "创建设备失败!");
            //绑定轮椅和医院的关系
            MtDeviceHospitalWheelchair mtDeviceHospitalWheelchair = new MtDeviceHospitalWheelchair();
            mtDeviceHospitalWheelchair.setHospitalId(mtDeviceHospital.getId());
            mtDeviceHospitalWheelchair.setWheelchairId(mtDeviceWheelchair.getId());
            mtDeviceHospitalWheelchair.setCreateTime(DateUtil.currentSeconds());
            mtDeviceHospitalWheelchair.setCreateBy(1L);
            Validator.validateTrue(retBool(mtDeviceHospitalWheelchairMapper.insert(mtDeviceHospitalWheelchair)), "数据保存失败!");

        }
        //查询订单
        List<MtDeviceOrder> list = this.list(Wrappers.<MtDeviceOrder>lambdaQuery().eq(MtDeviceOrder::getOrderDeviceWheelchairId, mtDeviceWheelchair.getId()).eq(MtDeviceOrder::getOrderState, 0).eq(MtDeviceOrder::getOrderPayState, 0).orderByDesc(MtDeviceOrder::getCreateTime));
        // 判断是否订单信息 - 有订单则结束订单 -无订单则绑定轮椅
        if (CollUtil.isNotEmpty(list)) {
            //修改订单信息
            MtDeviceOrder mtDeviceOrder = list.get(0);
            List<MtDeviceHospitalCost> mtDeviceHospitalCostList = mtDeviceHospitalCostMapper.selectList(Wrappers.<MtDeviceHospitalCost>lambdaQuery().eq(MtDeviceHospitalCost::getDeviceHospitalId, mtDeviceOrder.getOrderDeviceHospitalId()).eq(MtDeviceHospitalCost::getWheeType, mtDeviceWheelchair.getWheeType()).orderByDesc(MtDeviceHospitalCost::getCreateTime));
            Validator.validateTrue(CollUtil.isNotEmpty(mtDeviceHospitalCostList), "该医院未设置费用!");
            MtDeviceHospitalCost mtDeviceHospitalCost = mtDeviceHospitalCostList.get(0);
            //结束时间
            DateTime endTime = DateUtil.date();
            Integer orderUseTime = (int) DateUtil.between(DateUtil.date(ToolUtil.dateMillisecond(mtDeviceOrder.getCreateTime())), endTime, DateUnit.MINUTE);
            //计算时间是否超天数
            Integer minuten = 1440;
            Integer day = orderUseTime / minuten;//天
            Integer numy = orderUseTime % minuten;//分钟
            //超时金额
            BigDecimal orderOvertimeMoney = BigDecimal.ZERO;
            //订单总金额
            BigDecimal orderDiscountMoney = BigDecimal.ZERO;
            //订单支付金额
            BigDecimal orderPayMoney = BigDecimal.ZERO;
            //订单优惠金额
            BigDecimal orderMoney = BigDecimal.ZERO;
            //超时时长(暂时没用)
            Integer orderOverTime = 0;
            if (day == 0) {
                //计算优惠金额
                Integer feiYhTime = orderUseTime - mtDeviceHospitalCost.getCostDiscountDuration();
                //在优惠金额内
                if (feiYhTime <= 0) {
                    orderMoney = mtDeviceHospitalCost.getCostDiscountMoney();
                    orderPayMoney = mtDeviceHospitalCost.getCostDiscountMoney();
                    orderDiscountMoney = mtDeviceHospitalCost.getCostDiscountMoney();
                } else {
                    //判断是否超过正常时间

                    BigDecimal num = BigDecimal.valueOf(feiYhTime).divide(BigDecimal.valueOf(mtDeviceHospitalCost.getCostNormalDuration()), 0, BigDecimal.ROUND_UP);
                    orderMoney = mtDeviceHospitalCost.getCostDiscountMoney();
                    orderPayMoney = orderMoney.add(num.multiply(mtDeviceHospitalCost.getCostNormalMoney()).setScale(2, BigDecimal.ROUND_HALF_UP));
                    orderDiscountMoney = orderPayMoney;
                }
                //判断是否封顶
                if (orderPayMoney.compareTo(mtDeviceHospitalCost.getCostDailyCapMoney()) > 0) {
                    orderPayMoney = mtDeviceHospitalCost.getCostDailyCapMoney();
                }
            } else {
                //超出天的金额
                BigDecimal dayPayMoney = mtDeviceHospitalCost.getCostDailyCapMoney().multiply(BigDecimal.valueOf(day)).setScale(2, BigDecimal.ROUND_HALF_UP);
                //计算优惠金额
                Integer feiYhTime = numy - mtDeviceHospitalCost.getCostDiscountDuration();
                //在优惠金额内
                if (feiYhTime <= 0) {
                    orderMoney = mtDeviceHospitalCost.getCostDiscountMoney();
                    orderPayMoney = mtDeviceHospitalCost.getCostDiscountMoney();
                    orderDiscountMoney = mtDeviceHospitalCost.getCostDiscountMoney();
                } else {
                    //判断是否超过正常时间
                    BigDecimal num = BigDecimal.valueOf(feiYhTime).divide(BigDecimal.valueOf(mtDeviceHospitalCost.getCostNormalDuration()), 0, BigDecimal.ROUND_UP);
                    orderMoney = mtDeviceHospitalCost.getCostDiscountMoney();
                    orderPayMoney = orderMoney.add(num.multiply(mtDeviceHospitalCost.getCostNormalMoney()).setScale(2, BigDecimal.ROUND_HALF_UP));
                    orderDiscountMoney = orderPayMoney;
                }
                //判断是否封顶
                if (orderPayMoney.compareTo(mtDeviceHospitalCost.getCostDailyCapMoney()) > 0) {
                    orderPayMoney = mtDeviceHospitalCost.getCostDailyCapMoney();
                }
                orderMoney = orderMoney.add(dayPayMoney);
                orderPayMoney = orderPayMoney.add(dayPayMoney);
                orderDiscountMoney = orderDiscountMoney.add(dayPayMoney);
            }
            mtDeviceOrder.setOrderPutDeviceLockId(obj.getLockId());
            mtDeviceOrder.setOrderPutDeviceLockPassId(mtDeviceLockPass.getId());
            mtDeviceOrder.setOrderEndTime(ToolUtil.dateSecond(endTime));
            mtDeviceOrder.setOrderUseTime(orderUseTime);
            mtDeviceOrder.setOrderOvertime(orderOverTime);
            mtDeviceOrder.setOrderOvertimeMoney(orderOvertimeMoney);
            mtDeviceOrder.setOrderDiscountMoney(orderDiscountMoney);
            mtDeviceOrder.setOrderMoney(orderMoney);
            mtDeviceOrder.setOrderPayMoney(orderPayMoney);
            mtDeviceOrder.setOrderState((orderPayMoney.compareTo(BigDecimal.ZERO) == 1) ? 1 : 3);
            if (mtDeviceOrder.getOrderState() == 3) {
                mtDeviceOrder.setOrderPayState(1);
                mtDeviceOrder.setOrderPayTime(mtDeviceOrder.getOrderEndTime());
            }
            mtDeviceOrder.setUpdateTime(DateUtil.currentSeconds());
            //更新订单
            Validator.validateTrue(this.updateById(mtDeviceOrder), "订单更新失败!");
            //发送订阅消息
            //查询用户的openID
            List<DogUserConnect> userConnectList = dogUserConnectMapper.selectList(Wrappers.<DogUserConnect>lambdaQuery().eq(DogUserConnect::getUserId, list.get(0).getOrderUserId()));
            if (CollUtil.isNotEmpty(userConnectList)) {
                DogUserConnect dogUserConnect = userConnectList.get(0);
                if (StrUtil.isNotBlank(dogUserConnect.getMiniOpenid())) {
                    //开锁时间
                    String startTime = DateUtil.format(DateUtil.date(ToolUtil.dateMillisecond(mtDeviceOrder.getCreateTime())), "yyyy年MM月dd日 HH:mm");
                    //关锁时间
                    String endTimeDy = DateUtil.format(DateUtil.date(ToolUtil.dateMillisecond(mtDeviceOrder.getOrderEndTime())), "yyyy年MM月dd日 HH:mm");
                    weChatMiniService.pushMsg(dogUserConnect.getMiniOpenid(), startTime, endTimeDy);
                }
            }
        }
        //修改通道和轮椅的关系
        mtDeviceLockPass.setPassStatus(1);
        mtDeviceLockPass.setPassLockStatus(0);
        mtDeviceLockPass.setWheeId(mtDeviceWheelchair.getId());
        Validator.validateTrue(retBool(mtDeviceLockPassMapper.updateById(mtDeviceLockPass)), "锁通道更新失败!");
        //更新轮椅装填
        mtDeviceWheelchair.setWheeState(1);
        Validator.validateTrue(retBool(mtDeviceWheelchairMapper.updateById(mtDeviceWheelchair)), "轮椅信息更新失败!");
        return Boolean.TRUE;
    }


    /**
     * @Description: 设备订单支付
     * @Param: OrderBasketAddDto
     * @return: R
     * @Author: wph
     * @Date:
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @SneakyThrows
    public ApiOrderPrepayVo payOrder(Long id) {
        MtDeviceOrder mtDeviceOrder = this.getById(id);
        Validator.validateNotNull(mtDeviceOrder, "设备订单不存在!");
        Validator.validateEqual(mtDeviceOrder.getOrderState(), 1, "设备还未归还不能支付!");
        List<DogUserConnect> userConnectList = dogUserConnectMapper.selectList(Wrappers.<DogUserConnect>lambdaQuery().eq(DogUserConnect::getUserId, SecurityUtils.getUser().getUserId()));
        Validator.validateTrue(CollUtil.isNotEmpty(userConnectList), "用户未绑定微信不能付款");
        DogUserConnect dogUserConnect = userConnectList.get(0);
        Validator.validateTrue(StrUtil.isNotBlank(dogUserConnect.getMiniOpenid()), "用户未绑定微信不能付款");
        mtDeviceOrder.setOrderMainNo(serialNumberUtils.serialNumberGenerate().toString());
        mtDeviceOrder.setUpdateTime(DateUtil.currentSeconds());
        //更新订单
        Validator.validateTrue(this.updateById(mtDeviceOrder), "订单更新失败!");
        ApiOrderPrepayVo orderPrepayVo = new ApiOrderPrepayVo();
        orderPrepayVo.setOrderNo(mtDeviceOrder.getOrderMainNo());
        orderPrepayVo.setHnrbMoney(mtDeviceOrder.getOrderPayMoney());
        orderPrepayVo.setProName("设备订单");
        orderPrepayVo.setOpenid(dogUserConnect.getMiniOpenid());
        orderPrepayVo.setOrderType(0);
        orderPrepayVo.setOrderId(id);
        return orderPrepayVo;
    }

    /**
     * 小程序微信 Order订单 - 支付回调
     *
     * @param xmData
     * @return wph 2020/06/24
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @SneakyThrows
    public Boolean wxMiniPayLowerOrderCallback(String xmData) {
        // 解析
        WxPayOrderNotifyResult wxPayOrderNotifyResult = weChatMiniService.parseOrderNotifyResult(xmData);
        // 判断是否支付成功
        if (wxPayOrderNotifyResult.getReturnCode().equals("SUCCESS") && wxPayOrderNotifyResult.getResultCode()
                .equals("SUCCESS")) {
            String outTradeNo = wxPayOrderNotifyResult.getOutTradeNo();
            return paymentResultVerification(outTradeNo);
        }
        return Boolean.FALSE;
    }

    /**
     * 支付结果的校验
     *
     * @param outTradeNo
     * @return wph 2020/06/24
     */
    @SneakyThrows
    public Boolean paymentResultVerification(String outTradeNo) {
        //判断订单是否存在
        List<MtDeviceOrder> list = this.list(Wrappers.<MtDeviceOrder>lambdaQuery().eq(MtDeviceOrder::getOrderMainNo, outTradeNo));
        Validator.validateTrue(CollUtil.isNotEmpty(list), "订单不存在");
        MtDeviceOrder order = list.get(0);
        //修改订单状态
        order.setOrderPayTime(DateUtil.currentSeconds());
        order.setOrderState(3);
        order.setOrderPayState(1);
        order.setUpdateTime(DateUtil.currentSeconds());
        Validator.validateTrue(this.updateById(order), "支付回调失败!");
        //增加流水
        MtDeviceFlowingWater mtDeviceFlowingWater = new MtDeviceFlowingWater();
        mtDeviceFlowingWater.setSerialNo(order.getSerialNo());
        mtDeviceFlowingWater.setWaterUserId(order.getOrderUserId());
        mtDeviceFlowingWater.setWaterMoney(order.getOrderPayMoney());
        mtDeviceFlowingWater.setWaterType(0);
        mtDeviceFlowingWater.setInoutType(0);
        mtDeviceFlowingWater.setWaterAccount(0);
        mtDeviceFlowingWater.setWaterExplain("设备支付");
        mtDeviceFlowingWater.setCreateTime(DateUtil.currentSeconds());
        mtDeviceFlowingWater.setCreateBy(order.getOrderUserId());
        Validator.validateTrue(retBool(mtDeviceFlowingWaterMapper.insert(mtDeviceFlowingWater)), "支付回调失败!");
        return Boolean.TRUE;
    }

    /**
     * @Description: 关闭订单
     * @Param: OrderFromDto
     * @return: IPage<OrderVo>
     * @Author: wph
     * @Date:
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean closeOrder(Long id) {
        MtDeviceOrder dogNews = this.getById(id);
        Validator.validateNotNull(dogNews, "无此数据!");
        Validator.validateTrue(dogNews.getOrderState() == 0 || dogNews.getOrderState() == 1, "只有使用中或者代付款订单才能关闭");
        dogNews.setOrderState(4);
        dogNews.setUpdateTime(DateUtil.currentSeconds());
        dogNews.setUpdateBy(SecurityUtils.getSysUser().getUserId());
        Validator.validateTrue(this.updateById(dogNews), "操作失败!");
        return Boolean.TRUE;

    }

    /**
     * @Description: 结束订单
     * @Param: OrderFromDto
     * @return: IPage<OrderVo>
     * @Author: wph
     * @Date:
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean endOrder(Long id) {
        MtDeviceOrder mtDeviceOrder = this.getById(id);
        Validator.validateNotNull(mtDeviceOrder, "无此数据!");
        Validator.validateTrue(mtDeviceOrder.getOrderState() == 0, "只有使用中才能结束");
        MtDeviceHospital mtDeviceHospital = mtDeviceHospitalMapper.selectById(mtDeviceOrder.getOrderDeviceHospitalId());
        Validator.validateNotNull(mtDeviceHospital, "医院不存在!");
        MtDeviceWheelchair mtDeviceWheelchair = mtDeviceWheelchairMapper.selectById(mtDeviceOrder.getOrderDeviceWheelchairId());
        Validator.validateNotNull(mtDeviceWheelchair, "轮椅不存在!");
        List<MtDeviceHospitalCost> mtDeviceHospitalCostList = mtDeviceHospitalCostMapper.selectList(Wrappers.<MtDeviceHospitalCost>lambdaQuery().eq(MtDeviceHospitalCost::getDeviceHospitalId, mtDeviceOrder.getOrderDeviceHospitalId()).eq(MtDeviceHospitalCost::getWheeType, mtDeviceWheelchair.getWheeType()).orderByDesc(MtDeviceHospitalCost::getCreateTime));
        Validator.validateTrue(CollUtil.isNotEmpty(mtDeviceHospitalCostList), "该医院未设置费用!");
        MtDeviceHospitalCost mtDeviceHospitalCost = mtDeviceHospitalCostList.get(0);
        //结束时间
        DateTime endTime = DateUtil.date();
        Integer orderUseTime = (int) DateUtil.between(DateUtil.date(ToolUtil.dateMillisecond(mtDeviceOrder.getCreateTime())), endTime, DateUnit.MINUTE);
        //计算订单
        //计算时间是否超天数
        Integer minuten = 1440;
        Integer day = orderUseTime / minuten;//天
        Integer numy = orderUseTime % minuten;//分钟
        //超时金额
        BigDecimal orderOvertimeMoney = BigDecimal.ZERO;
        //订单总金额
        BigDecimal orderDiscountMoney = BigDecimal.ZERO;
        //订单支付金额
        BigDecimal orderPayMoney = BigDecimal.ZERO;
        //订单优惠金额
        BigDecimal orderMoney = BigDecimal.ZERO;
        //超时时长(暂时没用)
        Integer orderOverTime = 0;
        if (day == 0) {
            //计算优惠金额
            Integer feiYhTime = orderUseTime - mtDeviceHospitalCost.getCostDiscountDuration();
            //在优惠金额内
            if (feiYhTime <= 0) {
                orderMoney = mtDeviceHospitalCost.getCostDiscountMoney();
                orderPayMoney = mtDeviceHospitalCost.getCostDiscountMoney();
                orderDiscountMoney = mtDeviceHospitalCost.getCostDiscountMoney();
            } else {
                //判断是否超过正常时间

                BigDecimal num = BigDecimal.valueOf(feiYhTime).divide(BigDecimal.valueOf(mtDeviceHospitalCost.getCostNormalDuration()), 0, BigDecimal.ROUND_UP);
                orderMoney = mtDeviceHospitalCost.getCostDiscountMoney();
                orderPayMoney = orderMoney.add(num.multiply(mtDeviceHospitalCost.getCostNormalMoney()).setScale(2, BigDecimal.ROUND_HALF_UP));
                orderDiscountMoney = orderPayMoney;
            }
            //判断是否封顶
            if (orderPayMoney.compareTo(mtDeviceHospitalCost.getCostDailyCapMoney()) > 0) {
                orderPayMoney = mtDeviceHospitalCost.getCostDailyCapMoney();
            }
        } else {
            //超出天的金额
            BigDecimal dayPayMoney = mtDeviceHospitalCost.getCostDailyCapMoney().multiply(BigDecimal.valueOf(day)).setScale(2, BigDecimal.ROUND_HALF_UP);
            //计算优惠金额
            Integer feiYhTime = numy - mtDeviceHospitalCost.getCostDiscountDuration();
            //在优惠金额内
            if (feiYhTime <= 0) {
                orderMoney = mtDeviceHospitalCost.getCostDiscountMoney();
                orderPayMoney = mtDeviceHospitalCost.getCostDiscountMoney();
                orderDiscountMoney = mtDeviceHospitalCost.getCostDiscountMoney();
            } else {
                //判断是否超过正常时间
                BigDecimal num = BigDecimal.valueOf(feiYhTime).divide(BigDecimal.valueOf(mtDeviceHospitalCost.getCostNormalDuration()), 0, BigDecimal.ROUND_UP);
                orderMoney = mtDeviceHospitalCost.getCostDiscountMoney();
                orderPayMoney = orderMoney.add(num.multiply(mtDeviceHospitalCost.getCostNormalMoney()).setScale(2, BigDecimal.ROUND_HALF_UP));
                orderDiscountMoney = orderPayMoney;
            }
            //判断是否封顶
            if (orderPayMoney.compareTo(mtDeviceHospitalCost.getCostDailyCapMoney()) > 0) {
                orderPayMoney = mtDeviceHospitalCost.getCostDailyCapMoney();
            }
            orderMoney = orderMoney.add(dayPayMoney);
            orderPayMoney = orderPayMoney.add(dayPayMoney);
            orderDiscountMoney = orderDiscountMoney.add(dayPayMoney);
        }

        mtDeviceOrder.setOrderPutDeviceLockId(-1L);
        mtDeviceOrder.setOrderPutDeviceLockPassId(-1L);
        mtDeviceOrder.setOrderEndTime(ToolUtil.dateSecond(endTime));
        mtDeviceOrder.setOrderUseTime(orderUseTime);
        mtDeviceOrder.setOrderOvertime(orderOverTime);
        mtDeviceOrder.setOrderOvertimeMoney(orderOvertimeMoney);
        mtDeviceOrder.setOrderDiscountMoney(orderDiscountMoney);
        mtDeviceOrder.setOrderMoney(orderMoney);
        mtDeviceOrder.setOrderPayMoney(orderPayMoney);
        mtDeviceOrder.setOrderState((orderPayMoney.compareTo(BigDecimal.ZERO) == 1) ? 1 : 3);
        if (mtDeviceOrder.getOrderState() == 3) {
            mtDeviceOrder.setOrderPayState(1);
            mtDeviceOrder.setOrderPayTime(mtDeviceOrder.getOrderEndTime());
        }
        mtDeviceOrder.setUpdateTime(DateUtil.currentSeconds());
        //更新订单
        Validator.validateTrue(this.updateById(mtDeviceOrder), "订单更新失败!");
        //发送订阅消息
        //查询用户的openID
        List<DogUserConnect> userConnectList = dogUserConnectMapper.selectList(Wrappers.<DogUserConnect>lambdaQuery().eq(DogUserConnect::getUserId, mtDeviceOrder.getOrderUserId()));
        if (CollUtil.isNotEmpty(userConnectList)) {
            DogUserConnect dogUserConnect = userConnectList.get(0);
            if (StrUtil.isNotBlank(dogUserConnect.getMiniOpenid())) {
                //开锁时间
                String startTime = DateUtil.format(DateUtil.date(ToolUtil.dateMillisecond(mtDeviceOrder.getCreateTime())), "yyyy年MM月dd日 HH:mm");
                //关锁时间
                String endTimeDy = DateUtil.format(DateUtil.date(ToolUtil.dateMillisecond(mtDeviceOrder.getOrderEndTime())), "yyyy年MM月dd日 HH:mm");
                weChatMiniService.pushMsg(dogUserConnect.getMiniOpenid(), startTime, endTimeDy);
            }
        }
        //更新轮椅装填
        mtDeviceWheelchair.setWheeState(1);
        Validator.validateTrue(retBool(mtDeviceWheelchairMapper.updateById(mtDeviceWheelchair)), "轮椅信息更新失败!");
        return Boolean.TRUE;

    }

    /**
     * @Description: 修改订单金额
     * @Param: OrderFromDto
     * @return: IPage<OrderVo>
     * @Author: wph
     * @Date:
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean editObj(OrderEditDto obj) {
        MtDeviceOrder dogNews = this.getById(obj.getId());
        Validator.validateNotNull(dogNews, "无此数据!");
        Validator.equal(dogNews.getOrderState() == 1, "只有代付款订单才能修改金额");
        Validator.validateTrue(obj.getOrderPayMoney().compareTo(BigDecimal.ZERO) > 0, "修改的金额必须大于0");
        dogNews.setOrderState(1);
        dogNews.setOrderPayMoney(obj.getOrderPayMoney());
        dogNews.setUpdateTime(DateUtil.currentSeconds());
        dogNews.setUpdateBy(SecurityUtils.getSysUser().getUserId());
        Validator.validateTrue(this.updateById(dogNews), "操作失败!");
        return Boolean.TRUE;

    }

    /**
     * @Description: 确认退款(pc)
     * @Param: OrderFromDto
     * @return: IPage<PlatePageVo>
     * @Author: wph
     * @Date:
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @SneakyThrows
    public Boolean pcReturnObj(Long id) {
        MtDeviceOrder dogNews = this.getById(id);
        Validator.validateNotNull(dogNews, "无此数据!");
        Validator.validateEqual(dogNews.getOrderState(), 3, "已完成的订单才能退款!");
        AlipayTradeRefundResponse alipayTradeRefundResponse = new AlipayTradeRefundResponse();
        dogNews.setOrderState(5);
        Validator.validateTrue(this.updateById(dogNews), "退款开始失败!");
        //设置退款信息
        WxPayRefundRequest wxpayrefundrequest = new WxPayRefundRequest();
        //设备标识
        //wxpayrefundrequest.setDeviceInfo(orderinfoentity.getDeviceId());
        //商户订单号
        wxpayrefundrequest.setOutTradeNo(dogNews.getOrderMainNo());
        //商户退款单号
        wxpayrefundrequest.setOutRefundNo(dogNews.getOrderMainNo());
        //订单金额
        wxpayrefundrequest.setTotalFee(dogNews.getOrderPayMoney().multiply(BigDecimal.valueOf(100)).intValue());
        //退款金额
        wxpayrefundrequest.setRefundFee(dogNews.getOrderPayMoney().multiply(BigDecimal.valueOf(100)).intValue());

        WxPayRefundResult wxpayrefundresult = weChatMiniService.refund(wxpayrefundrequest);
        //调微信支付
        if ((wxpayrefundresult.getReturnCode().equals("SUCCESS") && wxpayrefundresult.getResultCode().equals("SUCCESS"))
                || (StrUtil.equals(alipayTradeRefundResponse.getMsg(), "Success") && StrUtil
                .equals(alipayTradeRefundResponse.getFundChange(), "Y"))) {
            dogNews.setUpdateTime(DateUtil.currentSeconds());
            dogNews.setOrderState(6);
            Validator.validateTrue(this.updateById(dogNews), "退款失败!");
            //增加流水
            MtDeviceFlowingWater mtDeviceFlowingWater = new MtDeviceFlowingWater();
            mtDeviceFlowingWater.setSerialNo(dogNews.getSerialNo());
            mtDeviceFlowingWater.setWaterUserId(dogNews.getOrderUserId());
            mtDeviceFlowingWater.setWaterMoney(dogNews.getOrderPayMoney().negate());
            mtDeviceFlowingWater.setWaterType(0);
            mtDeviceFlowingWater.setInoutType(1);
            mtDeviceFlowingWater.setWaterAccount(0);
            mtDeviceFlowingWater.setWaterExplain("正常订单退款");
            mtDeviceFlowingWater.setCreateTime(DateUtil.currentSeconds());
            mtDeviceFlowingWater.setCreateBy(SecurityUtils.getSysUser().getUserId());
            Validator.validateTrue(retBool(mtDeviceFlowingWaterMapper.insert(mtDeviceFlowingWater)), "支付回调失败!");
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }
}
